﻿// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "miHoYo/Character/Machine" {
	Properties {
		_Scale ("Scale Compared to Maya", Float) = 0.01

		_MainColor ("Main Color", Color) = (1, 1, 1, 1)

		//Transition Color
		_TransColor ("Transition Color", Color) = (1, 1, 1, 1)
		_ColorTransFactor ("Color Transition Factor", Range(0, 1)) = 1

		//Opaqueness
		_Opaqueness ("Opaqueness", Range(0, 1)) = 1
		_ZWrite ("Depth Write Switch (0: not write)", Range(0, 1)) = 1

		_BloomFactor ("Bloom Factor", float) = 0.25

		//Texture
		_MainTex ("Main Tex (RGB)", 2D) = "white" {}

		//Emission
		_Emission ("Emission Scaler", Range(1, 10)) = 1

		//Light
		_LightSpecColor ("Light Specular Color", Color) = (1, 1, 1, 1)

		//Shadow
		[HideInInspector]_LightArea ("Light Area Threshold", Range(0, 1)) = 0.51
		_ShadowMultColor ("Shadow Multiply Color", Color) = (0.9, 0.7, 0.75, 1)

		//Specular
		_Shininess ("Specular Shininess", Range(0, 100)) = 10
		_SpecMulti ("Specular Multiply Factor", Range(0, 1)) = 0.1

		//Outline
		_OutlineWidth ("Outline Width", Range(0, 100)) = 0.2
		_OutlineColor ("Outline Color", Color) = (0, 0, 0, 1)

		_ClipPlane ("Clip Plane (Model Space)", Vector) = (0,0,0,0)

		//Camera Fade
		_FadeDistance ("Fade Start Distance", Range(0.1, 10)) = 0.5
		_FadeOffset ("Fade Start Offset", Range(0, 10)) = 1
	}

	SubShader {
		Tags
		 { 
		 	"Queue"="Transparent"
			"RenderType"="Transparent"
			"IgnoreProjector"="True"
		 }
		LOD 200
		
		ZWrite [_ZWrite]
		
		//Base Pass
		Pass
		{
			Tags { "LightMode" = "ForwardBase" }

			Cull Back
			Blend SrcAlpha OneMinusSrcAlpha

			CGPROGRAM
			#include "../Common/Common_Util.cginc" 
			#include "../Common/Common_Lighting.cginc" 
			#pragma vertex vert
			#pragma fragment frag

			fixed4 _MainColor;
			sampler2D _MainTex;

			half3 _TransColor;
			half _ColorTransFactor;

			fixed _VertexAlphaFactor;

			half _Emission;
			fixed _EmissionFactor; 

			half _Opaqueness;

			fixed _LightArea;
			fixed4 _ShadowMultColor;

			float3 _CameraPos;
			half _Shininess;
			fixed _SpecMulti;

			fixed3 _LightSpecColor;

			float4 _ClipPlane;

			half _FadeDistance;
			half _FadeOffset;

			struct appdata
			{
				float4 vertex : POSITION;
			    float4 normal : NORMAL;
			    float4 texcoord : TEXCOORD0;
			};

			struct v2f {
				float4 position : POSITION;
				half2 texcoord : TEXCOORD0;
				fixed3 normal : TEXCOORD1;
				float3 objPos : TEXCOORD2;

				// x: diff factor
				// y: alpha
				fixed2 param : COLOR1;
			};

			v2f vert (appdata inData) 
			{
				v2f outData = (v2f)0;

				float4 objPos = mul(unity_ObjectToWorld, inData.vertex);
				outData.objPos = objPos.xyz / objPos.w;
				outData.texcoord = inData.texcoord.xy;

				// normal
				// 1. cannot get inverse transport of model matrix, just use _Object2World instead
				// there is no problem as long as no scale involved
				// 2. somehow the w component not be zero, so only use xyz
				outData.normal = normalize(mul((float3x3)unity_ObjectToWorld, inData.normal.xyz).xyz);

				//Diffuse
				// calculate diffuse factor
				outData.param.x = diffuse_factor(outData.normal, _WorldSpaceLightPos0.xyz);
				
				// Fade near camera
				half alpha = camera_fade(inData.vertex, _FadeOffset, _FadeDistance);

				// Cliping Plane
				alpha = plane_clip(alpha, inData.vertex, _ClipPlane);

				outData.param.y = alpha * _Opaqueness;

				outData.position = UnityObjectToClipPos(inData.vertex);

				return outData;
			} // End of vert

			fixed4 frag (v2f inData) : COLOR
			{
				fixed4 outColor = (fixed4)0;

				fixed3 diffColor = fixed3(1.0f, 1.0f, 1.0f); 
				fixed3 specColor = fixed3(0.0f, 0.0f, 0.0f);

				//Diffuse
				fixed3 baseTexColor = tex2D(_MainTex, inData.texcoord).rgb;

				// in shadow
				if (inData.param.x < _LightArea)
				{
					diffColor = baseTexColor * _ShadowMultColor;
				}
				// in light
				else
				{
					diffColor = baseTexColor;
				}

				//Specular
				// light dir
				fixed3 N = normalize(inData.normal);

				// pass camera pos
				fixed3 V = normalize(_WorldSpaceCameraPos.xyz - inData.objPos);
				
				fixed3 H = normalize(_WorldSpaceLightPos0 + V);
				fixed s = specular_factor(N, H, _Shininess);

				if (s > 0.5f ) // Front Specular
				{
					specColor = _LightSpecColor.rgb * _SpecMulti; 
				}

				//Original Color
				half3 origColor;
				origColor = diffColor * _MainColor.rgb + specColor;

				//Lerp Between Transition and Original Color
				outColor.rgb = lerp(_TransColor, origColor, _ColorTransFactor) * _Emission;

				outColor.a = inData.param.y;

				return outColor;
			} // End of frag

			ENDCG
		} // End of Base Pass

		//Simple Outline Pass With Clip Plane
		// 1. tangent as normal
		// 2. opaqueness from vertex
		// 3. clip plane
		Pass
		{
			Name "SIMPLE_CLIPPLANE"
			Cull Front
			Blend SrcAlpha OneMinusSrcAlpha

			CGPROGRAM
			#include "../Common/Common_Outline.cginc"
			#pragma vertex vert_simple_clipplane
			#pragma fragment frag_trans

			//With color transition
			half4 frag_trans (v2f inData) : SV_Target
			{
				half4 color = inData.color;

				color.a *= _Opaqueness * _Opaqueness;

				return color;
			}

			ENDCG
		} // End of Simple Outline Clipplane Pass

		//From-Tex Bloom Pass With Clip Plane
		Pass
		{
			Name "FROM_TEX_CLIPPLANE"
			ColorMask A

			CGPROGRAM
			#include "../Common/Common_Util.cginc" 
			#include "../Common/Common_Bloom.cginc"
			#pragma vertex vert_uv_clipplane
			#pragma fragment frag_fromtex_clipplane
			ENDCG
		} // End of Bloom Pass
	}
	FallBack "Diffuse"
}
